从H264/H265码流中获取宽、高及帧率

您所在的位置:网站首页 码率 分辨率 帧率怎么算的 从H264/H265码流中获取宽、高及帧率

从H264/H265码流中获取宽、高及帧率

2024-07-08 05:55| 来源: 网络整理| 查看: 265



在做码流分析时,图像分辨率、帧率这类的基本信息,当然不可少。本文介绍如何从NAL中计算到图像宽、高,还有分辨率。由于H264和H265有相似性,就在一起写了。

一、从码流获得宽、高 1、H264

宽高可从SPS字段计算得到,公式如下: Width = (pic_width_in_mbs_minus1+1)*16; Height = (pic_height_in_map_units_minus1+1)*16;

但以上是针对宽高是16的整数倍的情况,当不是16整数倍时,frame_cropping_flag值为1,frame_mbs_only_flag为1,公式如下: (也可以认为统一使用下面的公式)

width = ((pic_width_in_mbs_minus1 +1)*16) - frame_crop_left_offset*2 - frame_crop_right_offset*2; height= ((2 - frame_mbs_only_flag)* (pic_height_in_map_units_minus1 +1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);

比如一个1080P视频的SPS信息如下: pic_width_in_mbs_minus1 : 119 pic_height_in_map_units_minus1 : 67 frame_mbs_only_flag : 1 mb_adaptive_frame_field_flag : 0 direct_8x8_inference_flag : 1 frame_cropping_flag : 1    frame_crop_left_offset : 0    frame_crop_right_offset : 0    frame_crop_top_offset : 0    frame_crop_bottom_offset : 4

根据第二个公式 width = (119+1) * 16 - 0*2 - 0*2 = 1920 height = (2-1) * (67+1)*16 - 0*2 - 4*2 = 1088 - 8 = 1080

以上公式是一年多以前在网上找的,仔细看手册,上面的公式有局限性。根据H264手册Table6-1及7.4.2.1.1,参考mkvtoolnix代码,比如稳妥的计算方法如下:

// 宽高计算公式 width = (sps->pic_width_in_mbs_minus1+1) * 16; height = (2 - sps->frame_mbs_only_flag)* (sps->pic_height_in_map_units_minus1 +1) * 16); if(sps->frame_cropping_flag) { unsigned int crop_unit_x; unsigned int crop_unit_y; if (0 == sps->chroma_format_idc) // monochrome { crop_unit_x = 1; crop_unit_y = 2 - sps->frame_mbs_only_flag; } else if (1 == sps->chroma_format_idc) // 4:2:0 { crop_unit_x = 2; crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag); } else if (2 == sps->chroma_format_idc) // 4:2:2 { crop_unit_x = 2; crop_unit_y = 2 - sps->frame_mbs_only_flag; } else // 3 == sps.chroma_format_idc // 4:4:4 { crop_unit_x = 1; crop_unit_y = 2 - sps->frame_mbs_only_flag; } width -= crop_unit_x * (sps->frame_crop_left_offset + sps->frame_crop_right_offset); height -= crop_unit_y * (sps->frame_crop_top_offset + sps->frame_crop_bottom_offset); }

注: 一些H264分析工具,比如CodecVisa和H264Visa,1080P的视频,分辨率为1920x1088。这是不正确的。

2、H265

H.265类似,但SPS的字段不同了。公式如下:

width  = sps->pic_width_in_luma_samples; height = sps->pic_height_in_luma_samples; 当窗口有裁剪时(conformance_window_flag为1),计算如下:

sub_width_c = ((1==chroma_format_idc)||(2 == chroma_format_idc))&&(0==separate_colour_plane_flag)?2:1; sub_height_c = (1==chroma_format_idc)&& (0 == separate_colour_plane_flag)?2:1; width -= (sub_width_c*conf_win_right_offset + sub_width_c*conf_win_left_offset); height -= (sub_height_c*conf_win_bottom_offset + sub_height_c*conf_win_top_offset);

上式根据H265手册Table6-1及7.4.3.2.1小节计算宽、高。注意,手册里加了1,但实际不使用。 参考mkvtoolnix讨论:https://github.com/mbunkus/mkvtoolnix/issues/1152 注:对于1080P的视频,H265直接用pic_width_in_luma_samples及pic_height_in_luma_samples即得到正确的值。但对于一些奇葩的分辨率,还没有测试过。

三、帧率

H264和H265帧率计算公式相同,如下: max_framerate = (float)(sps->vui.vui_time_scale) / (float)(sps->vui.vui_num_units_in_tick); 使用x264编码YUV序列,设置为25fps时,time_scale为50,num_units_in_tick为1,计算得50fps,与实际不符。而x265用同样的参数编码,计算得到的帧率是正常的。

网上有说法,当nuit_field_based_flag为1时,要再除以2。另外说x264将该值设置为0,所以得到的值不是实际值。参见:http://forum.doom9.org/showthread.php?t=153019

目前还没研究透这一点。

李迟 2015.9.19



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3